package com.yunao.commons.serachcore.utils.lock;

import com.yunao.commons.serachcore.utils.JedisUtils;
import redis.clients.jedis.Jedis;

import java.util.concurrent.TimeUnit;

public class RedisBaseLock {

	private static final long LOCK_TIMEOUT = 300_000;
	
	private String lockKey;

	public RedisBaseLock(String lockKey) {
		this.lockKey = lockKey;
	}

	protected boolean tryGetLock(long time, TimeUnit unit) {
		long millisToWait = time <= 0 || unit == null ? 0 : unit.toMillis(time);
		long t = millisToWait == 0 ? 0 : System.currentTimeMillis() + millisToWait;
		try (Jedis jedis = JedisUtils.getResource()) {
			boolean flag = false;
			while (true) {
				if (t > 0 && System.currentTimeMillis() > t) {
					break;
				}
				flag = tryGetLock();
				if (flag) {
					break;
				} else {
					try {
						Thread.sleep(100l);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
			return flag;
		}
	}
	
	private boolean tryGetLock() {
		try (Jedis jedis = JedisUtils.getResource()) {
			long expireTime = System.currentTimeMillis() + LOCK_TIMEOUT + 1;
			if (jedis.setnx(lockKey, String.valueOf(expireTime)) == 1) {
				return true;
			}

			// 超时
			if (checkLockTimeout(jedis)) {
				String preExpireTimestr = jedis.getSet(lockKey, String.valueOf(expireTime));
				if (System.currentTimeMillis() > Long.parseLong(preExpireTimestr)) {
					return true;
				}
			}
			return false;
		}
	}

	protected void releaseLock() {
		try (Jedis jedis = JedisUtils.getResource()) {
			if (!checkLockTimeout(jedis)) {
				jedis.del(lockKey);
			}
		}
	}

	private boolean checkLockTimeout(Jedis jedis) {
		return System.currentTimeMillis() > Long.parseLong(jedis.get(lockKey));
	}

}

